<<<<<<< HEAD
<script>
  import { Terminal } from 'xterm';
  import 'xterm/css/xterm.css';
  import { listen } from '@tauri-apps/api/event';
  
  export default {
    data() {
      return {
        terminal: null,
        unlisten: null
      };
    },
    mounted() {
      this.setupTerminal();
    },
    methods: {
      async setupTerminal() {
        this.terminal = new Terminal();
        this.terminal.open(document.getElementById('term'));
        // this.terminal.open(this.$refs.terminal);
        this.terminal.resize(130,20);
  
        // 监听 Tauri 后端发送的终端输出
        unlisten = await listen('receive_terminal_output', (event) => {
          this.terminal.writeln(event.payload);
        });
        
      },
    },
  };
  </script>

<template>
  <div>
    <!-- <div>pppppppppp</div> -->
    <div id="term"></div>
    
  </div>
</template>
  
<style scoped>
</style>
=======
<template>
  <div class="terminal-app">
    <div id="tab-bar-container">
      <div id="tab-bar" ref="tabBar"></div>
      <button id="new-terminal-button" ref="newTerminalButton">+</button>
      <button id="start-renode-button" @click="start">Start Renode</button>
    </div>
    <div id="terminal-container" ref="terminalContainer"></div>
  </div>
</template>

<script>
import { Terminal } from "xterm";
import { FitAddon } from "xterm-addon-fit";
import { invoke } from "@tauri-apps/api/core";
import { listen } from "@tauri-apps/api/event";

export default {
  name: "TerminalApp",
  data() {
    return {
      terminals: [],
    };
  },
  mounted() {
    this.newTerminalButton?.addEventListener("click", this.createNewTerminal);

    listen("exit_terminal", (event) => {
      const terminalId = event.payload;
      this.closeTerminal(terminalId);
    });

    this.createNewTerminal();

    window.addEventListener("resize", this.debouncedFitTerminal);
  },
  beforeDestroy() {
    this.newTerminalButton?.removeEventListener(
      "click",
      this.createNewTerminal
    );
    window.removeEventListener("resize", this.debouncedFitTerminal);

    this.terminals.forEach((terminal) => {
      this.closeTerminal(terminal.id);
    });
  },
  computed: {
    newTerminalButton() {
      return this.$refs.newTerminalButton;
    },
    tabBar() {
      return this.$refs.tabBar;
    },
    terminalContainer() {
      return this.$refs.terminalContainer;
    },
  },
  methods: {
    async createNewTerminal() {
      try {
        const fitAddon = new FitAddon();
        const term = new Terminal({
          theme: {
            background: "#2f2f2f",
          },
        });
        term.loadAddon(fitAddon);

        const terminalElement = document.createElement("div");
        terminalElement.classList.add("terminal-instance");
        this.terminalContainer.appendChild(terminalElement);

        term.open(terminalElement);
        fitAddon.fit();
        term.focus();

        await new Promise((resolve) => setTimeout(resolve, 10));

        const rows = term.rows;
        const cols = term.cols;
        const terminalId = await invoke("create_shell", { rows, cols });

        const writer = new PtyWriter(terminalId);

        let readInterval;
        const startReading = async () => {
          readInterval = window.setInterval(async () => {
            try {
              const data = await invoke("read_pty", { terminalId });
              if (data) {
                term.write(data);
              }
            } catch (error) {
              clearInterval(readInterval);
            }
          }, 100);
        };

        startReading();
        term.onData((data) => {
          writer.enqueue(data);
        });
        function debounce(func, wait) {
          let timeout;
          return () => {
            clearTimeout(timeout);
            timeout = setTimeout(func, wait);
          };
        }
        async function fitTerminal() {
          try {
            fitAddon.fit();
            const updatedRows = term.rows;
            const updatedCols = term.cols;
            await invoke("resize_pty", {
              rows: updatedRows,
              cols: updatedCols,
            });
          } catch (error) {
            console.error(`调整终端大小时出错:`, error);
          }
        }
        const debouncedFitTerminal = debounce(fitTerminal, 200);

        window.addEventListener("resize", debouncedFitTerminal);
        debouncedFitTerminal();
        const tabElement = document.createElement("button");
        tabElement.classList.add("tab");
        tabElement.innerHTML = `<span class="tab-number">终端 ${this.terminals.length + 1}</span>`;
        Object.assign(tabElement.style, {
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'space-between',
          padding: '5px 10px',
          marginRight: '5px',
          backgroundColor: '#3c3c3c',
          color: '#fff',
          border: 'none',
          cursor: 'pointer',
          borderRadius: '0',
          whiteSpace: 'nowrap',
          flexShrink: '0',
          minWidth: '120px'
        });

        const closeTabButton = document.createElement("button");
        closeTabButton.innerHTML = "×";
        closeTabButton.classList.add("close-tab");
        Object.assign(closeTabButton.style, {
          marginLeft: 'auto',
          background: 'none',
          border: 'none',
          color: '#fff',
          cursor: 'pointer',
          fontSize: '14px',
          padding: '0',
          lineHeight: '1'
        });

        closeTabButton.addEventListener("click", (e) => {
          e.stopPropagation();
          this.closeTerminal(terminalId);
        });
        tabElement.appendChild(closeTabButton);
        tabElement.addEventListener("click", () => {
          this.activateTerminal(terminalId);
        });

        this.tabBar.appendChild(tabElement);
        this.scrollTabBarToEnd();

        const terminalInstance = {
          id: terminalId,
          terminal: term,
          element: terminalElement,
          tabElement: tabElement,
          readInterval: readInterval,
          writer: writer,
        };
        this.terminals.push(terminalInstance);
        this.activateTerminal(terminalId);
      } catch (error) {
        console.error("创建新终端时出错:", error);
      }
    },

    activateTerminal(terminalId) {
      this.terminals.forEach((t) => {
        if (t.id === terminalId) {
          t.element.style.display = 'block';
          t.tabElement.style.backgroundColor = '#555';
          t.tabElement.style.borderBottom = '2px solid #00aaff';
          t.terminal.focus();
        } else {
          t.element.style.display = 'none';
          t.tabElement.style.backgroundColor = '#3c3c3c';
          t.tabElement.style.borderBottom = 'none';
        }
      });
    },
    async closeTerminal(terminalId) {
      const terminalIndex = this.terminals.findIndex(
        (t) => t.id === terminalId
      );
      if (terminalIndex === -1) return;

      const terminalInstance = this.terminals[terminalIndex];

      try {
        await invoke("close_terminal", { terminalId });

        terminalInstance.element.remove();
        terminalInstance.tabElement.remove();
        clearInterval(terminalInstance.readInterval);

        this.terminals.splice(terminalIndex, 1);

        if (
          terminalInstance.tabElement.classList.contains("active") &&
          this.terminals.length > 0
        ) {
          this.activateTerminal(this.terminals[0].id);
        }
      } catch (error) {
        console.error(`关闭终端 ${terminalId} 时出错:`, error);
      }
    },

    scrollTabBarToEnd() {
      this.tabBar.scrollTo({
        left: this.tabBar.scrollWidth,
        behavior: "smooth",
      });
    },

    async start() {
      try {
        await this.createNewTerminal();
        let path=await invoke("local_path");
        this.$nextTick(() => {
      const newTerminal = this.terminals[this.terminals.length - 1];
      if (newTerminal && newTerminal.writer) {
        // 切换到指定路径
        newTerminal.writer.enqueue('cd ' + path + '\r');
        // 启动 Renode 控制台
        setTimeout(() => {
          newTerminal.writer.enqueue('renode --console\r');
        setTimeout(async () => {
          newTerminal.writer.enqueue('start @../platforms/stm32f103.resc\r');
            // await invoke('startrenode');
        }, 1000);
        }, 100);
      }
    });
  } 
catch (error) {
        console.error("启动 Renode 时出错:", error);
      }
    },
  },

  created() {
  },
};

class PtyWriter {
  constructor(terminalId) {
    this.queue = [];
    this.activeCount = 0;
    this.concurrency = 2;
    this.terminalId = terminalId;
  }

  enqueue(data) {
    this.queue.push(data);
    this.processQueue();
  }

  async processQueue() {
    if (this.activeCount >= this.concurrency || this.queue.length === 0) return;
    this.activeCount++;
    const data = this.queue.shift();
    try {
      await invoke("write_pty", { terminalId: this.terminalId, data });
    } catch (error) {
      console.error(`向终端 ${this.terminalId} 写入数据时出错:`, error);
    }
    this.activeCount--;
    this.processQueue();
  }
}
</script>

<style scoped>
.terminal-instance {
  display: none;
  position: relative;
  flex: 1;
  border: none;
  background-color: #2f2f2f;
}

.terminal-app {
  margin: 0;
  padding: 0;
  background-color: #2f2f2f;
  color: #fff;
  font-family: Arial, sans-serif;
  height: 100vh;
  display: flex;
  flex-direction: column;
}

#tab-bar-container {
  display: flex;
  align-items: center;
  background-color: #1e1e1e;
  padding: 5px;
  overflow: hidden;
  flex-shrink: 0;
}

#tab-bar {
  display: flex;
  flex-grow: 1;
  overflow-x: auto;
  white-space: nowrap;
}

.tab.active {
  background-color: #555;
}

.tab .close-tab {
  margin-left: 10px;
  background: none;
  border: none;
  color: #fff;
  cursor: pointer;
  font-size: 14px;
  padding: 0;
  line-height: 1;
}

#new-terminal-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  margin-left: 5px;
  background-color: #3c3c3c;
  color: #fff;
  border: none;
  border-radius: 3px;
  cursor: pointer;
  flex-shrink: 0;
  font-size: 20px;
  line-height: 20px;
  padding: 0;
}

#new-terminal-button:hover {
  background-color: #555;
}

#start-renode-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100px;
  height: 30px;
  margin-left: 5px;
  background-color: #3c3c3c;
  color: #fff;
  border: none;
  border-radius: 3px;
  cursor: pointer;
  flex-shrink: 0;
  font-size: 14px;
}

#start-renode-button:hover {
  background-color: #555;
}

#terminal-container {
  flex-grow: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.terminal-instance {
  display: none;
  position: relative;
  flex: 1;
  border: none;
  background-color: #2f2f2f;
}

.terminal-instance button.close-terminal {
  position: absolute;
  top: 5px;
  right: 5px;
  z-index: 10;
  padding: 2px 5px;
  background-color: #ff4d4d;
  color: #fff;
  border: none;
  cursor: pointer;
}

#tab-bar::-webkit-scrollbar {
  height: 8px;
}

#tab-bar::-webkit-scrollbar-track {
  background: #1e1e1e;
}

#tab-bar::-webkit-scrollbar-thumb {
  background-color: #555;
  border-radius: 4px;
}

.tab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 5px 10px;
  margin-right: 5px;
  background-color: #3c3c3c;
  color: #fff;
  border: none;
  cursor: pointer;
  border-radius: 0;
  white-space: nowrap;
  flex-shrink: 0;
  min-width: 120px;
}

.tab.active {
  background-color: #555;
  border-bottom: 2px solid #00aaff;
}

.tab .tab-number {
  margin-right: 10px;
}

.tab .close-tab {
  margin-left: auto;
  background: none;
  border: none;
  color: #fff;
  cursor: pointer;
  font-size: 14px;
  padding: 0;
  line-height: 1;
}
</style>
>>>>>>> v3.0
